package com.moo2u2.android.oaktononthego.providers;

import java.util.HashMap;

import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;

import com.moo2u2.android.oaktononthego.timesheet.dao.TimesheetDatabaseHelper;
import com.moo2u2.android.oaktononthego.timesheet.dao.TimesheetEntryTable;
import com.moo2u2.android.oaktononthego.timesheet.dao.TimesheetTable;

/**
 * A very simple implementation of a content provider.
 */
public class TimesheetProvider extends ContentProvider {
	/**
	 * The authority we use to get to our sample provider.
	 */
	public static final String AUTHORITY = "com.moo2u2.android.oakton.providers.TimesheetProvider";

	// A projection map used to select columns from the database
	private final HashMap<String, String> mTimesheetsProjectionMap,
			mEntriesProjectionMap;

	// Uri matcher to decode incoming URIs.
	private final UriMatcher mUriMatcher;

	// The incoming URI matches the timesheet table URI pattern
	private static final int TIMESHEET = 1;

	// The incoming URI matches the timesheet table row ID URI pattern
	private static final int TIMESHEET_ID = 2;

	// The incoming URI matches the entry table URI pattern
	private static final int ENTRY = 3;

	// The incoming URI matches the entry table row ID URI pattern
	private static final int ENTRY_ID = 4;

	// Handle to a new DatabaseHelper.
	private TimesheetDatabaseHelper mOpenHelper;

	/**
	 * The MIME type of {@link #CONTENT_URI}.
	 */
	public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.example.api-demos-throttle";

	/**
	 * The MIME type of a {@link #CONTENT_URI} sub-directory of a single row.
	 */
	public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.example.api-demos-throttle";

	/**
	 * Global provider initialization.
	 */
	public TimesheetProvider() {
		// Create and initialize URI matcher.
		mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
		mUriMatcher
				.addURI(AUTHORITY, TimesheetTable.TIMESHEET_TABLE, TIMESHEET);
		mUriMatcher.addURI(AUTHORITY, TimesheetTable.TIMESHEET_TABLE + "/#",
				TIMESHEET_ID);

		mUriMatcher.addURI(AUTHORITY, TimesheetEntryTable.ENTRY_TABLE, ENTRY);
		mUriMatcher.addURI(AUTHORITY, TimesheetEntryTable.ENTRY_TABLE + "/#",
				ENTRY_ID);

		mTimesheetsProjectionMap = new HashMap<String, String>();
		mTimesheetsProjectionMap.put(TimesheetTable.KEY_ROWID,
				TimesheetTable.KEY_ROWID);
		mTimesheetsProjectionMap.put(TimesheetTable.KEY_ENDDATE,
				TimesheetTable.KEY_ENDDATE);
		mTimesheetsProjectionMap.put(TimesheetTable.KEY_SUBMITTED,
				TimesheetTable.KEY_SUBMITTED);

		mEntriesProjectionMap = new HashMap<String, String>();
		mEntriesProjectionMap.put(TimesheetEntryTable.KEY_ROWID,
				TimesheetEntryTable.KEY_ROWID);
		mEntriesProjectionMap.put(TimesheetEntryTable.KEY_TIMESHEET,
				TimesheetEntryTable.KEY_TIMESHEET);
		mEntriesProjectionMap.put(TimesheetEntryTable.KEY_DAY,
				TimesheetEntryTable.KEY_DAY);
		mEntriesProjectionMap.put(TimesheetEntryTable.KEY_TYPE,
				TimesheetEntryTable.KEY_TYPE);
		mEntriesProjectionMap.put(TimesheetEntryTable.KEY_SUBTYPE,
				TimesheetEntryTable.KEY_SUBTYPE);
		mEntriesProjectionMap.put(TimesheetEntryTable.KEY_HOURS,
				TimesheetEntryTable.KEY_HOURS);
		mEntriesProjectionMap.put(TimesheetEntryTable.KEY_NOTES,
				TimesheetEntryTable.KEY_NOTES);
	}

	/**
	 * Perform provider creation.
	 */
	@Override
	public boolean onCreate() {
		mOpenHelper = new TimesheetDatabaseHelper(getContext());
		// Assumes that any failures will be reported by a thrown exception.
		return true;
	}

	/**
	 * Handle incoming queries.
	 */
	@Override
	public Cursor query(Uri uri, String[] projection, String selection,
			String[] selectionArgs, String sortOrder) {

		// Constructs a new query builder and sets its table name
		SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
		SQLiteDatabase db = mOpenHelper.getReadableDatabase();

		String[] nyselectionArgs;
		Cursor c = null;

		switch (mUriMatcher.match(uri)) {
		case TIMESHEET:
			qb.setTables(TimesheetTable.TIMESHEET_TABLE);
			qb.setProjectionMap(mTimesheetsProjectionMap);
			break;

		case ENTRY:
			qb.setTables(TimesheetEntryTable.ENTRY_TABLE);
			qb.setProjectionMap(mEntriesProjectionMap);
			break;

		case TIMESHEET_ID:
			qb.setTables(TimesheetTable.TIMESHEET_TABLE);
			qb.setProjectionMap(mTimesheetsProjectionMap);
			qb.appendWhere(TimesheetTable.KEY_ROWID + "=?");
			// selectionArgs =
			// DatabaseUtils.appendSelectionArgs(selectionArgs, new
			// String[] { uri.getLastPathSegment() });
			nyselectionArgs = new String[selectionArgs.length + 1];
			System.arraycopy(selectionArgs, 0, nyselectionArgs, 0,
					selectionArgs.length);
			nyselectionArgs[selectionArgs.length] = uri.getLastPathSegment();
			break;

		case ENTRY_ID:
			// qb.setTables(TimesheetEntryTable.ENTRY_TABLE);
			// qb.setProjectionMap(mEntriesProjectionMap);
			// qb.appendWhere(TimesheetTable.KEY_ROWID + "=?");
			// selectionArgs =
			// DatabaseUtils.appendSelectionArgs(selectionArgs, new
			// String[] { uri.getLastPathSegment() });
			nyselectionArgs = new String[selectionArgs.length + 1];
			System.arraycopy(selectionArgs, 0, nyselectionArgs, 0,
					selectionArgs.length);
			nyselectionArgs[selectionArgs.length] = uri.getLastPathSegment();
			c = db.rawQuery("SELECT " + TimesheetEntryTable.KEY_ROWID + ", "
					+ TimesheetEntryTable.KEY_TIMESHEET + ", "
					+ TimesheetEntryTable.KEY_DAY + ", "
					+ TimesheetEntryTable.KEY_TYPE + ", "
					+ TimesheetEntryTable.KEY_SUBTYPE + ", "
					+ TimesheetEntryTable.KEY_HOURS + ", "
					+ TimesheetEntryTable.KEY_NOTES + " WHERE "
					+ TimesheetEntryTable.KEY_TIMESHEET + " = ?"
					+ TimesheetEntryTable.KEY_DAY + " = ?", new String[] { "1",
					"0" });
			break;

		default:
			throw new IllegalArgumentException("Unknown URI " + uri);
		}

		if (TextUtils.isEmpty(sortOrder)) {
			sortOrder = "";// "_id ASC";
		}

		if (c == null)
			c = qb.query(db, projection, selection, selectionArgs, null, null,
					sortOrder);

		c.setNotificationUri(getContext().getContentResolver(), uri);
		return c;
	}

	/**
	 * Return the MIME type for an known URI in the provider.
	 */
	@Override
	public String getType(Uri uri) {
		switch (mUriMatcher.match(uri)) {
		case TIMESHEET:
			return CONTENT_TYPE;
		case TIMESHEET_ID:
			return CONTENT_ITEM_TYPE;
		case ENTRY:
			return CONTENT_TYPE;
		case ENTRY_ID:
			return CONTENT_ITEM_TYPE;
		default:
			throw new IllegalArgumentException("Unknown URI " + uri);
		}
	}

	/**
	 * Handler inserting new data.
	 */
	@Override
	public Uri insert(Uri uri, ContentValues initialValues) {
		Log.i(this.getClass().getSimpleName(), "Inserting values...");

		String table = "";
		Uri uriBase = null;
		switch (mUriMatcher.match(uri)) {
		case TIMESHEET:
			table = TimesheetTable.TIMESHEET_TABLE;
			uriBase = TimesheetTable.CONTENT_ID_URI_BASE;
			break;
		case ENTRY:
			table = TimesheetEntryTable.ENTRY_TABLE;
			uriBase = TimesheetEntryTable.CONTENT_ID_URI_BASE;
			break;
		default:
			throw new IllegalArgumentException("Unknown URI " + uri);
		}

		ContentValues values;

		if (initialValues != null) {
			values = new ContentValues(initialValues);
		} else {
			values = new ContentValues();
		}

		SQLiteDatabase db = mOpenHelper.getWritableDatabase();

		long rowId = db.insert(table, null, values);

		// If the insert succeeded, the row ID exists.
		if (rowId > 0) {
			Uri noteUri = ContentUris.withAppendedId(uriBase, rowId);
			getContext().getContentResolver().notifyChange(noteUri, null);
			return noteUri;
		}

		throw new SQLException("Failed to insert row into " + uri);
	}

	/**
	 * Handle deleting data.
	 */
	@Override
	public int delete(Uri uri, String where, String[] whereArgs) {
		Log.i(this.getClass().getSimpleName(), "Deleting...");

		SQLiteDatabase db = mOpenHelper.getWritableDatabase();
		// String finalWhere;

		int count = 0;

		switch (mUriMatcher.match(uri)) {
		case TIMESHEET:
			count = db.delete(TimesheetTable.TIMESHEET_TABLE, where, whereArgs);
			break;

		case TIMESHEET_ID:
			// finalWhere =
			// DatabaseUtils.concatenateWhere(TimesheetTable.KEY_ROWID +
			// " = " + ContentUris.parseId(uri), );
			count = db.delete(
					TimesheetTable.TIMESHEET_TABLE,
					where + TimesheetTable.KEY_ROWID + " = "
							+ ContentUris.parseId(uri), whereArgs);
			break;

		default:
			throw new IllegalArgumentException("Unknown URI " + uri);
		}

		getContext().getContentResolver().notifyChange(uri, null);

		return count;
	}

	/**
	 * Handle updating data.
	 */
	@Override
	public int update(Uri uri, ContentValues values, String where,
			String[] whereArgs) {
		Log.i(this.getClass().getSimpleName(), "Updating values...");

		SQLiteDatabase db = mOpenHelper.getWritableDatabase();
		int count = 0;
		// String finalWhere;

		switch (mUriMatcher.match(uri)) {
		case TIMESHEET:
			count = db.update(TimesheetTable.TIMESHEET_TABLE, values, where,
					whereArgs);
			break;

		case TIMESHEET_ID:
			// finalWhere = DatabaseUtils
			// .concatenateWhere(TimesheetTable.KEY_ROWID + " = "
			// + ContentUris.parseId(uri), where);
			count = db.update(
					TimesheetTable.TIMESHEET_TABLE,
					values,
					where + TimesheetTable.KEY_ROWID + " = "
							+ ContentUris.parseId(uri), whereArgs);
			break;

		default:
			throw new IllegalArgumentException("Unknown URI " + uri);
		}

		getContext().getContentResolver().notifyChange(uri, null);

		return count;
	}
}